/*
 创建Promise实例的第四种方案：Promise.all/any/race
   let p = Promise.all([promises])
     + 方法返回值是一个新的promise实例
     + [promises]：包含多个promise实例的集合
   监测集合中每一个实例的状态
     + 只要有一个实例是失败态，则p就是失败的，值是当前这一项失败的原因
     + 所有项都成功，则p的状态是成功，它的值也是一个数组集合，按照原有[promises]的顺序，依次存储每一项成功的结果！！
     + 如果[promises]集合中有一项不是promise实例，则内部会把其变为状态为成功，值是本身的实例

   Promise.any：[promises]集合中有一项成功，则p就是成功的(值就是成功这一项的值)，所有项都失败，p才是失败的(值是AggregateError: All promises were rejected)；「不是ES6中增加的，是ES11中新增的，所以现代浏览器的版本如果低一些，也是不兼容的」

   Promise.race：谁快则以谁为准，不论成功还是失败
 */

/* let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1);
    }, 2000);
});
let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(2);
    }, 1000);
});
let p3 = Promise.reject(3);
let p4 = 4; //默认转换为promise实例 => p4=Promise.resolve(4);

let p = Promise.all([p1, p2, p3, p4]);
p.then(values => {
    console.log('都成功：', values); //[1,2,3,4] 和原始集合的顺序保持一致
}).catch(reason => {
    console.log('有一项失败：', reason);
}); */

//===================================
/*
 async/await：Promise+Generator的“语法糖” ，让promise的语法使用起来更简洁「ES8新增的」
   async：用来修饰一个函数，目的是让函数返回一个promise实例 
     返回实例的状态是成功还是失败，取决于函数执行的细节：
     + 函数执行报错，则返回失败的实例（值是报错原因）
     + 函数执行的返回值，如果本身就是一个promise实例，则以自己返回的实例为主
     + 如果返回值不是新的promise实例，则返回一个状态是成功，值是返回的值promise实例
     async最主要的作用是：我们如果想在函数中使用await，则当前函数必须经过async来修饰！！

   await：可以等待异步操作结束，返回promise实例的状态是成功，再去执行当前上下文“下面的代码”
     await只能用在函数中
     let value = await [promise实例]
       + await后面要跟着一个promise实例
         await 10; 如果不是实例，则默认转换为状态为成功，值是本身的实例 -> await Promise.resolve(10)
         await func(); 先把函数执行，把返回值作为一个promise实例去监测
       + 等待[promise实例]的状态是成功，把成功的值赋值给value，当前上下文中，下面的代码才会继续执行！
       + 如果实例是失败的，则下面的代码不会再执行，也不会给value赋值！！
 */

// 面试题「附加思考题」：
/**
 * 实现一个LazyMan，可以按照以下方式调用:
    LazyMan(“Hank”)输出:
    Hi! This is Hank!

    LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
    Hi! This is Hank!
    //等待10秒..
    Wake up after 10
    Eat dinner~

    LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
    Hi This is Hank!
    Eat dinner~
    Eat supper~

    LazyMan(“Hank”).eat(“supper”).sleepFirst(5)输出
    //等待5秒
    Wake up after 5
    Hi This is Hank!
    Eat supper
 */

/* // 面试题：设计一个延迟函数（delay），执行这个函数，可以让两个操作之间，间隔一段时间再执行
const delay = function delay(interval = 1000) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve();
        }, interval);
    });
};
(async () => {
    console.log(1);
    await delay(3000); //等待1000ms...
    console.log(2);
})(); */


/* const fn = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(100);
        }, 2000);
    });
};

// 如果处理await后的promise实例，为失败的情况？
(async function () {
    try {
        let value = await fn();
        // 监测的实例状态是成功，则执行下面的代码
        console.log('成功:', value);
    } catch (reason) {
        // 这里就是处理await后面实例是失败的状况
        console.log('失败:', reason);
    }
})(); */

/* const func = async () => {
    console.log(a);
    return 10;
};
console.log(func()); //状态:rejected 值:a is not defined */

/* const func = async () => {
    return 10;
};
console.log(func()); //状态:fulfilled 值:10 */


//====================
/*
 Promise基础知识「第一阶段」 
   @1 Promise是干啥的？（或者是其作用）
     从现在开始需要培养一种编程意识：但凡遇到异步编程的代码(例如ajax请求、定时器等)，而且是需要在异步操作结束，处理啥事情的情况下，我们大部分情况都应该用Promise对其进行管理！
   @2 new Promsie时候，传递的executor函数的细节知识点
   @3 创建promise实例的N种方案「包含如何修改实例的状态和值」
     + new Promsie((resolve,reject)=>{  ...  })
     + Promise.resolve/reject()
     + .then/catch(onfulfilled,onrejected) 可以创建新的promise实例
       + THEN链机制
       + THEN链的穿透性
     + Promise.all/any/race([promises])
     + 基于async修饰函数
   @4 then和catch（含finally）的语法
 */

/* 
// 基于Promise管理ajax异步操作
const queryData = () => {
    return new Promise(resolve => {
        let xhr = new XMLHttpRequest;
        xhr.open('GET', './data.json');
        xhr.onreadystatechange = () => {
            let { readyState, status, responseText } = xhr;
            if (readyState === 4 && status === 200) {
                let data = JSON.parse(responseText);
                // 请求成功后:把promise实例变为fulfilled，值就是从服务器获取的结果
                resolve(data);
            }
        };
        xhr.send();
    });
};
queryData().then(value => {
    console.log('请求成功:', value);
    // ...
});
(async () => {
    let value = await queryData();
    console.log('请求成功:', value);
    // ...
})(); 
*/